<?php

namespace wchat\wx\V3;

use Exception;
use JetBrains\PhpStorm\ArrayShape;
use wchat\wx\SmallProgram;
use wchat\wx\V3\Libs\TransferDetail;

class WxV3Withdrawal extends SmallProgram
{


    use WxV3PaymentTait;


    /**
     * @param string $orderNo
     * @param string $batch_name
     * @param string $batch_remark
     * @param TransferDetail[] $details
     * @return array
     * @throws
     */
    public function payment(string $orderNo, string $batch_name, string $batch_remark, array $details): array
    {
        $body = $this->create($orderNo, $batch_name, $batch_remark, $details);

        $sign = $this->signature('POST', '/v3/pay/transactions/batches', $json = json_encode($body, JSON_UNESCAPED_UNICODE));

        $client = $this->createClient($sign, $json);
        $client->post('/v3/pay/transactions/batches');
        $client->close();

        $json = json_decode($client->getBody(), TRUE);
        if (!isset($json['prepay_id'])) {
            throw new Exception('微信支付调用失败');
        }

        return $this->createResponse($json, $body);
    }


    /**
     * @param string $orderNo
     * @param string $batch_name
     * @param string $batch_remark
     * @param array $details
     * @return array[]
     */
    #[ArrayShape(['transfer_detail_list' => "array", 'total_amount' => "int", 'total_num' => "int", 'batch_remark' => "string", 'batch_name' => "string", 'out_batch_no' => ""])]
    private function create(string $orderNo, string $batch_name, string $batch_remark, array $details): array
    {
        $total                = 0;
        $body                 = ['transfer_detail_list' => []];
        $body['out_batch_no'] = $orderNo;
        $body['batch_name']   = $batch_name;
        $body['batch_remark'] = $batch_remark;
        $body['total_num']    = count($details);
        foreach ($details as $detail) {
            $total                          += $detail->transfer_amount;
            $body['transfer_detail_list'][] = $detail->toArray();
        }
        $body['total_amount'] = $total;
        return $body;
    }



    /**
     * @param TransferDetail $detail
     * @return array<'out_bill_no', 'transfer_bill_no', 'create_time', 'state'>
     * @throws Exception
     */
    #[ArrayShape([])]
    public function transfer(TransferDetail $detail): array
    {
        $payConfig = $this->getPayConfig();
        $body      = $detail->toArray();
        if ($payConfig->typeIsApp()) {
            $body['appid'] = $payConfig->pay->wx->appId;
        } else {
            $body['appid'] = $payConfig->appId;
        }
        $sign = $this->signature('POST', '/v3/fund-app/mch-transfer/transfer-bills', $json = json_encode($body, JSON_UNESCAPED_UNICODE));

        $client = $this->createClient($sign, $json);
        $client->post('/v3/fund-app/mch-transfer/transfer-bills');
        $client->close();

        Kiri::getLogger()->println($client->getBody());

        if ($client->getStatusCode() == 200) {
            return json_decode($client->getBody(), TRUE);
        }
        throw new Exception('转账申请发起失败');
    }

}
